#include "XiolControllerManager.h"

#include <assert.h> 
#include <sstream> 
#include <map> 

class DebugGamepadControllerListener : public Xiol::Controller::Listener
{
public:
	virtual void onComponentChanged( Xiol::Controller* controller, Xiol::Controller::ComponentTypeID componentTypeID, int componentID )
	{
		std::string componentTypeName = Xiol::Controller::getComponentTypeName( componentTypeID );
		std::string componentName;
		std::stringstream stream;
		switch ( componentTypeID )
		{
			case Xiol::Controller::ComponentType_Button : 
				componentName = Xiol::Controller::getButtonName( static_cast<Xiol::Controller::ButtonID>(componentID) );
				if ( controller->isButtonPressed( static_cast<Xiol::Controller::ButtonID>(componentID) ) )
					stream << "pressed";
				else 
					stream << "not pressed";
				break;
			case Xiol::Controller::ComponentType_Trigger : 
				componentName = Xiol::Controller::getTriggerName( static_cast<Xiol::Controller::TriggerID>(componentID) );
				stream << "position: " << (int)controller->getTriggerPosition( static_cast<Xiol::Controller::TriggerID>(componentID) );
				break;
			case Xiol::Controller::ComponentType_Thumbstick : 
				componentName = Xiol::Controller::getThumbstickName( static_cast<Xiol::Controller::ThumbstickID>(componentID) );
				SHORT x;
				SHORT y;
				controller->getThumbstickPosition( static_cast<Xiol::Controller::ThumbstickID>(componentID), x, y); 
				stream << "position: x:" << x << " y: " << y;				
				break;
			case Xiol::Controller::ComponentType_VibrationMotor : 
				componentName = Xiol::Controller::getVibrationMotorName( static_cast<Xiol::Controller::VibrationMotorID>(componentID) );
				WORD speed = controller->getVibrationMotorSpeed( static_cast<Xiol::Controller::VibrationMotorID>(componentID) );
				stream << "speed: " << speed;
				break;
		}

		std::string batteryInformation;
//		if ( controller->hasBattery(Xiol::Controller::Battery_Xiol::Controller) )
//			batteryInformation += "onboard bat: " + controller->getBatteryLevel(Xiol::Controller::Battery_Xiol::Controller)

		bool hascb = controller->hasBattery(Xiol::Controller::Battery_Controller);
		bool haspb = controller->hasBattery(Xiol::Controller::Battery_Headset);

		printf("Xiol::Controller %d (cb:%d,%d,%d/hb:%d,%d,%d)- %s - %s - %s\n", 
			controller->getControllerIndex(),
			hascb, controller->getBatteryType(Xiol::Controller::Battery_Controller), controller->getBatteryLevel(Xiol::Controller::Battery_Controller),
			haspb, controller->getBatteryType(Xiol::Controller::Battery_Headset), controller->getBatteryLevel(Xiol::Controller::Battery_Headset),
			componentTypeName.c_str(), componentName.c_str(), stream.str().c_str()  );

		// Check motors
		if ( componentTypeID==Xiol::Controller::ComponentType_Button || 
			 componentTypeID==Xiol::Controller::ComponentType_Trigger )
		{
			if ( controller->isButtonPressed( Xiol::Controller::Button_A ) )
			{
				WORD speedL = controller->getTriggerPosition( Xiol::Controller::Trigger_Left ) * 255;
				controller->setVibrationMotorSpeed( Xiol::Controller::VibrationMotor_Left, speedL );
				WORD speedR = controller->getTriggerPosition( Xiol::Controller::Trigger_Right ) * 255;
				controller->setVibrationMotorSpeed( Xiol::Controller::VibrationMotor_Right, speedR );
			}
			//else 
			//{
		//		controller->setVibrationMotorSpeed( Xiol::Controller::VibrationMotor_Left, 0 );
		//		controller->setVibrationMotorSpeed( Xiol::Controller::VibrationMotor_Right, 0 );
		//	}
		}
	}
};

class DebugControllerManagerListener : public Xiol::ControllerManager::Listener
{
public:
	virtual void onControllerConnected( Xiol::ControllerManager* controllerManager, Xiol::Controller* controller )
	{
		printf("Controller %d - Connected (%s)\n", controller->getControllerIndex(), controller->getSubTypeName() );
		
		// Create a listener for the Controller, register it and remember it
		Xiol::Controller::Listener* listener = new DebugGamepadControllerListener();
		mListeners.insert( std::make_pair( controller, listener ) );
		controller->addListener( listener );
	}

	virtual void onControllerDisconnecting( Xiol::ControllerManager* controllerManager, Xiol::Controller* controller )
	{
		printf("Controller %d - Disconnecting\n", controller->getControllerIndex() );
		
		// Retrieve the listener we created for the Controller, unregister it, delete it and forget it
		std::map<Xiol::Controller*, Xiol::Controller::Listener*>::iterator itr = mListeners.find( controller );
		assert( itr!=mListeners.end() );
		Xiol::Controller::Listener* listener = (*itr).second;
		controller->removeListener( listener );
		mListeners.erase( itr );
		delete listener;
	}

private:
	std::map<Xiol::Controller*, Xiol::Controller::Listener*> mListeners;	
};

int main()
{
 	Xiol::ControllerManager manager;

	DebugControllerManagerListener listener;
	manager.addListener( &listener );
	while (1)
	{
		manager.update();
		Sleep(10);
	}
	return 0;
}
